/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.omega_r.libs.omegarecyclerview.base;

import com.omega_r.libs.omegarecyclerview.util.Utils;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.multimodalinput.event.TouchEvent;

import java.util.List;

public class BaseViewHolder implements Component.ClickedListener {
    protected Component itemView;

    protected ListContainer listContainer;
    protected float startPointX;
    protected ComponentContainer leftContainer, rightContainer;
    protected int itemLeftTrans = 0, itemMiddleTrans, itemRightTrans;
    protected static boolean isListContDrag;

    private ItemListener itemListener;

    public BaseViewHolder(Component itemView) {
        this.itemView = itemView;
    }

    public BaseViewHolder(Component itemView, ListContainer listContainer) {
        this(itemView, listContainer, 0, 0);
    }

    public BaseViewHolder(Component itemView, ListContainer listContainer, int leftXmlId, int rightXmlId) {
        this(itemView);
        this.listContainer = listContainer;
        if (leftXmlId == 0 && rightXmlId == 0) return;

        if (leftXmlId != 0) {
            leftContainer = (ComponentContainer) LayoutScatter.getInstance(itemView.getContext()).parse(leftXmlId, null, false);
        }
        if (rightXmlId != 0) {
            rightContainer = (ComponentContainer) LayoutScatter.getInstance(itemView.getContext()).parse(rightXmlId, null, false);
        }
        addLeftRightComponent();

        itemView.setTouchEventListener((component, touchEvent) -> {
            if (itemListener != null) itemListener.itemTouchEvent(component, touchEvent);

            switch (touchEvent.getAction()) {
                case TouchEvent.PRIMARY_POINT_DOWN:
                    leftRightLayoutDragStart(touchEvent);
                    break;
                case TouchEvent.POINT_MOVE:
                    leftRightLayoutDraging(touchEvent);
                    break;
                case TouchEvent.PRIMARY_POINT_UP:
                case TouchEvent.CANCEL:
                    leftRightLayoutDragEnd(0);
                    break;
            }
            return true;
        });

        //保证在listContainer滑动时候，item不会滑动
        listContainer.setScrolledListener(new Component.ScrolledListener() {
            @Override
            public void onContentScrolled(Component component, int i, int i1, int i2, int i3) {

            }

            @Override
            public void scrolledStageUpdate(Component component, int newStage) {
                isListContDrag = newStage == Component.SCROLL_IDLE_STAGE ? false : true;
            }
        });
    }

    @Override
    public void onClick(Component component) {
    }

    protected Component findComponentById(int resId) {
        return itemView.findComponentById(resId);
    }

    public void updateView(BaseBean baseBean) {
    }

    public interface ItemListener {
        void itemTouchEvent(Component component, TouchEvent touchEvent);
    }

    public void setItemListener(ItemListener itemListener) {
        this.itemListener = itemListener;
    }

    //添加左右布局
    private void addLeftRightComponent() {
        listContainer.setLongClickable(false);

        DirectionalLayout directionalLayout = new DirectionalLayout(itemView.getContext());
        directionalLayout.setLayoutConfig(new ComponentContainer.LayoutConfig(1000000
                , ComponentContainer.LayoutConfig.MATCH_CONTENT));
        directionalLayout.setOrientation(DirectionalLayout.HORIZONTAL);

        if (leftContainer != null) directionalLayout.addComponent(leftContainer);
        directionalLayout.addComponent(itemView);
        if (rightContainer != null) directionalLayout.addComponent(rightContainer);

        if (leftContainer != null) {
            leftContainer.setLayoutRefreshedListener(component -> {
                itemMiddleTrans = -leftContainer.getWidth();
                itemView.setTranslationX(itemMiddleTrans);
            });
        }

        itemView.setLayoutConfig(new ComponentContainer.LayoutConfig((int) Utils.getScreenWidth(itemView.getContext())
                , ComponentContainer.LayoutConfig.MATCH_CONTENT));

        itemView = directionalLayout;
    }

    public void leftRightLayoutDragStart(TouchEvent touchEvent) {
        listContainer.setEnabled(true);
        itemMiddleTrans = leftContainer != null ? -leftContainer.getWidth() : 0;
        itemRightTrans = -(rightContainer != null ? rightContainer.getWidth() : 0) - (leftContainer != null ? leftContainer.getWidth() : 0);
        startPointX = touchEvent.getPointerScreenPosition(touchEvent.getIndex()).getX();
    }

    public void leftRightLayoutDraging(TouchEvent touchEvent) {
        if (isListContDrag) return;
        float scrollX = touchEvent.getPointerScreenPosition(touchEvent.getIndex()).getX() - startPointX;
        if (scrollX >= -20 && scrollX < 20) return;

        listContainer.setEnabled(false);

        float minTranslationX = getLeftWidth() + getRightWidth();
        float maxTranslationX = 0;
        float nowTranslation = itemView.getTranslationX() + scrollX;

        if (nowTranslation < minTranslationX) nowTranslation = minTranslationX;
        if (nowTranslation > maxTranslationX) nowTranslation = maxTranslationX;

        itemView.setTranslationX(nowTranslation);
        startPointX = touchEvent.getPointerScreenPosition(touchEvent.getIndex()).getX();
    }

    private int getLeftWidth() {
        ComponentContainer tmp = (ComponentContainer) itemView;
        if (leftContainer == null || tmp.getComponentAt(0) == null) return 0;
        return -tmp.getComponentAt(0).getWidth();
    }

    private int getRightWidth() {
        ComponentContainer tmp = (ComponentContainer) itemView;
        if (rightContainer == null) return 0;
        return -tmp.getComponentAt(tmp.getChildCount() - 1).getWidth();
    }

    /**
     * 获取目前item的状态
     *
     * @return 0滑动中，1左显示，2中间显示，3右显示
     */
    public int getItemState() {
        float nowTranslation = itemView.getTranslationX();
        if (nowTranslation == itemLeftTrans) return 1;
        if (nowTranslation == itemMiddleTrans) return 2;
        if (nowTranslation == itemRightTrans) return 3;
        return 0;
    }

    /**
     * 滑动结束
     *
     * @param dragDirection 1左边显示，2显示中间，3显示右边，其它数字自动
     */
    public void leftRightLayoutDragEnd(int dragDirection) {
        if (dragDirection != 0 && dragDirection == getItemState()) return;

        float minTranslationX = getLeftWidth() + getRightWidth();
        float maxTranslationX = 0;
        float scrollToMinX = getLeftWidth() + getRightWidth() / 2f;
        float scrollToMaxX = getLeftWidth() / 2f;
        float nowTranslation = itemView.getTranslationX();

        int moveDistance = 0, moveTrans = 0;
        if (dragDirection == 1) {
            moveDistance = (int) (maxTranslationX - nowTranslation);
            moveTrans = itemLeftTrans;
        } else if (dragDirection == 2) {
            moveTrans = itemMiddleTrans;
            moveDistance = (int) (getLeftWidth() - nowTranslation);
        } else if (dragDirection == 3) {
            moveDistance = (int) (minTranslationX - nowTranslation);
            moveTrans = itemRightTrans;
        } else {
            if (nowTranslation < scrollToMinX) {
                moveDistance = (int) (minTranslationX - nowTranslation);
                moveTrans = itemRightTrans;
            } else if (nowTranslation > scrollToMaxX) {
                moveDistance = (int) (maxTranslationX - nowTranslation);
                moveTrans = itemLeftTrans;
            } else {
                moveTrans = itemMiddleTrans;
                moveDistance = (int) (getLeftWidth() - nowTranslation);
            }
        }

        int finalMoveTrans = moveTrans;
        itemView.createAnimatorProperty().moveByX(moveDistance).setDuration(100).setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
            }

            @Override
            public void onStop(Animator animator) {
            }

            @Override
            public void onCancel(Animator animator) {
                itemView.setTranslationX(finalMoveTrans);
            }

            @Override
            public void onEnd(Animator animator) {
                itemView.setTranslationX(finalMoveTrans);
            }

            @Override
            public void onPause(Animator animator) {
            }

            @Override
            public void onResume(Animator animator) {
            }
        }).start();
    }

    //item折叠
    protected void setItemExtend(ComponentContainer extend, Component trigger, BaseBean bean,
                                 boolean isCloseOtherItem, boolean isAnimator, int position, OnClickListener onClickListener) {
        if (bean.isExpand()) {
            if (!isAnimator) {
                extend.setTranslationY(0);
                extend.setVisibility(Component.VISIBLE);
            } else if (extend.getVisibility() == Component.HIDE) {
                extend.setVisibility(Component.INVISIBLE);
            }
        }
        if (!bean.isExpand()) {
            if (!isAnimator) extend.setTranslationY(-extend.getHeight());
            extend.setVisibility(Component.HIDE);
        }

        trigger.setClickedListener(component -> {
            bean.setExpand(!bean.isExpand());
            setClickListener(onClickListener, bean, position);
            if (!isAnimator) {      //无动画
                if (bean.isExpand() && isCloseOtherItem) otherItemClose(position);
                listContainer.getItemProvider().notifyDataChanged();
                return;
            }

            //有动画情况
            if (bean.isExpand()) {
                if (isCloseOtherItem) otherItemClose(position);
                listContainer.getItemProvider().notifyDataChanged();
            }

            AnimatorValue animatorValue = new AnimatorValue();
            animatorValue.setCurveType(Animator.CurveType.LINEAR);
            animatorValue.setValueUpdateListener((animatorValue1, v) -> {
                float exHeight = extend.getHeight();
                if (bean.isExpand()) {
                    extend.setAlpha((float) (1.0 * v * 2) > 1 ? 1 : (float) (1.0 * v * 2));
                    extend.setTranslationY(exHeight * v - exHeight);
                    if (v > 0.1 && extend.getVisibility() != Component.VISIBLE) {
                        extend.setVisibility(Component.VISIBLE);
                    }
                } else {
                    extend.setTranslationY(-exHeight * v);
                }
            });
            animatorValue.setDuration(200);

            animatorValue.setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                }

                @Override
                public void onStop(Animator animator) {
                }

                @Override
                public void onCancel(Animator animator) {
                }

                @Override
                public void onEnd(Animator animator) {
                    if (!bean.isExpand()) {
                        listContainer.getItemProvider().notifyDataSetItemChanged(position);
                    }
                }

                @Override
                public void onPause(Animator animator) {
                }

                @Override
                public void onResume(Animator animator) {
                }
            });
            animatorValue.start();
        });
    }

    //其它item收起
    public void otherItemClose(int position) {
        int viNum = listContainer.getVisibleIndexCount();
        BaseProvider baseProvider = (BaseProvider) listContainer.getItemProvider();
        List providerList = baseProvider.providerList;
        for (int i = 0; i < viNum; i++) {
            int itemIndex = listContainer.getItemPosByVisibleIndex(i);
            BaseBean bean = (BaseBean) providerList.get(itemIndex);
            if (itemIndex != position) {
                bean.setExpand(false);
            }
        }
    }

    private void setClickListener(OnClickListener onClickListener, BaseBean bean, int position) {
        if (onClickListener != null) {
            if (bean.isExpand()) {
                onClickListener.onCollapse(bean, position);
            } else {
                onClickListener.onExpand(bean, position);
            }
        }
    }


    public interface OnClickListener {
        void onCollapse(BaseBean bean, int position);

        void onExpand(BaseBean bean, int position);
    }
}
